#include "mqtt.h"
#include <QTime>
mqtt::mqtt(QObject *parent,QString hostname,int id,uint16_t port,double con_co2,double con_tem,double con_hum,double con_light) : QObject(parent),hostname(hostname),id(id),port(port),con_co2(con_co2),con_tem(con_tem),con_hum(con_hum),con_light(con_light)
{

    client=new QMqttClient;
    client->setHostname(hostname);
    client->setPort(port);



    // 设置遗嘱信息
       QString willTopic = QString("smartfarm/%1/controller/status").arg(id);
       QJsonObject willPayload;
       willPayload["farm_id"] = id;
       willPayload["status"] = "off";
       willPayload["time_stamp"] = QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss");
       QByteArray willMessage = QJsonDocument(willPayload).toJson();

       // 配置遗嘱：QoS=1, retained=true
       client->setWillTopic(willTopic);
       client->setWillMessage(willMessage);
       client->setWillQoS(1);
       client->setWillRetain(true);

       // 初始化重连定时器
          reconnectTimer = new QTimer(this);
          reconnectTimer->setSingleShot(true);
          connect(reconnectTimer, &QTimer::timeout, this, [this]() {
              if (client->state() == QMqttClient::Disconnected) {
                  qDebug() << "Attempting to reconnect...";
                  client->connectToHost();
              }
          });

          // 初始化心跳检测定时器
          keepAliveTimer = new QTimer(this);
          connect(keepAliveTimer, &QTimer::timeout, this, [this]() {
              if (client->state() == QMqttClient::Disconnected) {
                  qDebug() << "Connection lost, attempting to reconnect...";
                  reconnectTimer->start(1000); // 1秒后尝试重连
              }
          });
          keepAliveTimer->start(5000); // 每5秒检查一次连接



    QMqttTopicFilter sub_topic;
    // mqtt.cpp (构造里把订阅的 farm_id 改为 this->id)
    connect(client, &QMqttClient::connected, [=]() {
        qDebug() << "MQTT Client connected";
        QMqttTopicFilter sub_topic;
        sub_topic.setFilter(QStringLiteral("smartfarm/%1/controller/cmd").arg(id));
        client->subscribe(sub_topic);
        sub_topic.setFilter(QStringLiteral("smartfarm/%1/setConstantValue/cmd").arg(id));
        client->subscribe(sub_topic);
        sub_topic.setFilter(QStringLiteral("smartfarm/%1/getConstantValue/cmd").arg(id));
        client->subscribe(sub_topic);

        QString willTopic = QString("smartfarm/%1/controller/status").arg(id);
        QJsonObject willPayload;
        willPayload["farm_id"] = id;
        willPayload["status"] = "on";
        willPayload["time_stamp"] = QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss");
        QByteArray willMessage = QJsonDocument(willPayload).toJson();
        client->publish(QMqttTopicName(willTopic), willMessage, 0, false);

    });

//    connect(client, &QMqttClient::disconnected, []() {
//        qDebug() << "MQTT Client disconnected";
//    });


    // 修改原有的断开信号处理
       connect(client, &QMqttClient::disconnected, this, [this]() {
           qDebug() << "MQTT Client disconnected";
           reconnectTimer->start(1000); // 1秒后尝试重连
       });

    client->connectToHost();


    // 连接消息信号
    connect(client, &QMqttClient::messageReceived, this, &mqtt::handleMessage);

}

int mqtt::sendData(int id, double co2, double tem, double hum, double light, QString time)
{

    QJsonObject obj;
    obj["farm_id"] = id;
    obj["co2"] = co2;
    obj["temperature"] = tem;
    obj["humidity"] = hum;
    obj["light_intensity"] = light;
    obj["time_stamp"] = time;

    QJsonDocument doc(obj);
    QByteArray payload = doc.toJson();
    QMqttTopicName push_topic;
    push_topic.setName(QString("smartfarm/%1/sensor/data").arg(id));

    // 发布消息到MQTT主题
    if (client && client->state() == QMqttClient::Connected) {
        QMqttTopicName topic(push_topic);
        client->publish(topic, payload, 0, false);
        //qDebug() << "Published to topic:" << push_topic << "Payload:" << payload;
        return 0;
    } else {
        qWarning() << "MQTT client not connected. Cannot publish data.";
        return -1;
    }




}

int mqtt::sendOnline(int id, QString status, QString time)
{
    // 创建JSON对象
    QJsonObject obj;
    obj["farm_id"] = id;
    obj["status"] = status;
    obj["time_stamp"] = time;

    // 转换为JSON
    QJsonDocument doc(obj);
    QByteArray payload = doc.toJson();

    // 设置主题并发布
    QString topicName = QString("smartfarm/%1/controller/status").arg(id);

    if (client && client->state() == QMqttClient::Connected) {
        client->publish(topicName, payload, 1, true); // QoS=1, 保留消息
        //qDebug() << "Published:" << topicName << payload;
        return 0;
    }

    qWarning() << "MQTT not connected";
    return -1;


}

int mqtt::sendLimitData(int id, double co2, double tem, double hum, double light, QString time)
{
//    // 创建JSON对象
    QJsonObject obj;
    obj["farm_id"] = id;
    obj["co2"] = co2;
    obj["temperature"] = tem;
    obj["humidity"] = hum;
    obj["light_intensity"] = light;
    obj["time_stamp"] = time;

    // 转换为JSON文档
    QJsonDocument doc(obj);
    QByteArray payload = doc.toJson();

    // 设置主题名称（根据第一张图片的路径格式）
    QString topicName = QString("smartfarm/%1/constantValue/data").arg(id);

    // 发布消息
    if (client && client->state() == QMqttClient::Connected) {
        client->publish(topicName, payload, 1, false); // QoS=1，保留消息
        //qDebug() << "Published:" << topicName << payload;
        return 0;
    }

    qWarning() << "MQTT not connected";
    return -1;



}


void mqtt::handleMessage(const QByteArray &message, const QMqttTopicName &topic )
{
    QJsonObject obj = QJsonDocument::fromJson(message).object();
    // 获取主题名称字符串
    QString topicName = topic.name();

    // 主要根据主题区分，这是最可靠的方法
    if (topicName.endsWith("/controller/cmd")) {
        processControllerCmd(obj);
    }
    else if (topicName.endsWith("/setConstantValue/cmd")) {
        processConstantValueCmd(obj);
    }
    else if (topicName.endsWith("/getConstantValue/cmd")) {
        processGetConstantValue(obj);
    }

}

void mqtt::processControllerCmd(const QJsonObject &obj)
{

    conCmd.farm_id = obj["farm_id"].toInt();
    conCmd.status = obj["status"].toString();
    conCmd.time_stamp = obj["time_stamp"].toString();
   // qDebug()<<cmd.farm_id<<" "<<cmd.status<<"  "<<cmd.time_stamp;
    // 处理启用/禁用农场逻辑
}

// mqtt.cpp：收到 setConstantValue/cmd 时，更新本地副本并发信号
void mqtt::processConstantValueCmd(const QJsonObject &obj)
{
    contValueCmd.farm_id        = obj.value("farm_id").toInt(id);
    contValueCmd.co2            = obj.value("co2").toDouble(con_co2);
    contValueCmd.temperature    = obj.value("temperature").toDouble(con_tem);
    contValueCmd.humidity       = obj.value("humidity").toDouble(con_hum);
    contValueCmd.light_intensity= obj.value("light_intensity").toDouble(con_light);
    contValueCmd.time_stamp     = obj.value("time_stamp").toString();

    // 只处理当前设备的 id
    if (contValueCmd.farm_id != id) return;

    // 覆盖本地保存的常量（供 getConstantValue 时回传）
    con_co2   = contValueCmd.co2;
    con_tem   = contValueCmd.temperature;
    con_hum   = contValueCmd.humidity;
    con_light = contValueCmd.light_intensity;

    // ★ 通知上层（Widget）更新 UI 阈值并下发到下位机
    emit constantValueReceived(contValueCmd.farm_id,
                               contValueCmd.co2,
                               contValueCmd.temperature,
                               contValueCmd.humidity,
                               contValueCmd.light_intensity,
                               contValueCmd.time_stamp);

    // （可选）回发一条最新阈值，作为 ACK/广播
    const QString now = QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss");
    sendLimitData(id, con_co2, con_tem, con_hum, con_light, now);
}

void mqtt::processGetConstantValue(const QJsonObject &obj)
{
    getConValue.farm_id=obj["farm_id"].toInt();
    getConValue.time_stamp = obj["time_stamp"].toString();

    // 获取当前日期和时间
//    QDateTime currentDateTime = QDateTime::currentDateTime();

//    QString time=currentDateTime.toString("yyyy-MM-dd hh:mm:ss");

//qDebug()<<time;

    sendLimitData(id,con_co2,con_tem,con_hum,con_light, getConValue.time_stamp);
}



